package main

import (
	"bytes"
	"container/list"
	"flag"
	"fmt"
	"github.com/pion/stun"
	"github.com/pion/turn/v2"
	"log"
	"math"
	"net"
	"strconv"
	"strings"
	"time"
)

func main1() {
	fmt.Println("hello")
}

func main2() {
	var name string = "zhangsan"
	name = "lisi"

	fmt.Println(name)
}

func main3() {
	var name string = "zhangsan"
	var age int = 18

	fmt.Println(name, age)
}

func main4() {
	var (
		name string
		age  int
		addr string
	)

	fmt.Println(name, age, addr)
}

func main5() {
	name := "zhangsan"
	age := 18

	fmt.Println(name, age)
	fmt.Printf("%T, %T", name, age) // string int
}

func main6() {
	num := 100

	fmt.Printf("num:%d, 内存:%p\n", num, &num)

	num = 200

	fmt.Printf("num:%d, 内存:%p", num, &num)
}

func main7() {
	a := 10
	b := 20

	a, b = b, a

	fmt.Println(a, b)
}

func test() (int, int) {
	return 100, 200
}

func main8() {
	a, _ := test()
	fmt.Println(a)
}

func main9() {
	// iota 常量计数器
	const (
		a = iota
		b
		c
		d = "zhangsan"
		e
		f = 100
		g
		h = iota
		i
	)

	const (
		j = iota
		k
	)

	fmt.Println(a, b, c, d, e, f, g, h, i, j, k)
}

func main10() {
	var flag bool = true

	fmt.Println(flag)
}

func main11() {
	var age int = 18
	var pai float64 = 3.14

	fmt.Printf("%T, %d\n", age, age)
	fmt.Printf("%T, %.2f\n", pai, pai)
}

func main12() {
	val1 := 'a'
	val2 := "a"

	fmt.Printf("%T, %T\n", val1, val2)
}

func main13() {
	a := 5
	b := 5.9
	c := float64(a)
	d := int(b)

	fmt.Printf("%T\n", a)
	fmt.Printf("%T\n", b)
	fmt.Printf("%T\n", c)
	fmt.Printf("%T, d = %d\n", d, d)
}

func main14() {
	var x int
	var y float64

	fmt.Println("输入两个数: ")
	fmt.Scan(&x, &y)
	fmt.Println("x = ", x, ", y = ", y)
}

func main15() {
	var a int
	fmt.Scan(&a)

	if a > 20 {
		fmt.Println("a > 20")
	} else if a >= 15 {
		fmt.Println("a >= 15")
	} else {
		fmt.Println("a < 15")
	}
}

func main16() {
	score := 90

	switch score {
	case 90:
		fmt.Println("A")
	case 80:
		fmt.Println("B")
	case 70:
		fmt.Println("C")
	case 60:
		fmt.Println("D")

	}
}

func main17() {
	for i := 0; i < 5; i++ {
		fmt.Println(i)
	}

	a := 10

	for a < 100 {
		fmt.Println(a)
		a += 5
	}
}

func main18() {
	str := "0132456"

	fmt.Println(len(str))
	fmt.Printf("%c", str[3])
}

func main19() {
	str := "abcdefg"

	//for i := 0; i < len(str); i++ {
	//	fmt.Println(str[i])
	//	// fmt.Printf("%c", str[i])
	//}

	for i, v := range str {
		fmt.Printf("%d, %c\n", i, v)
	}
}

func add(a, b int) int {
	return a + b
}

func addAndSub(a, b int) (int, int) {
	return a + b, a - b
}

func main20() {
	var a int
	var b int
	fmt.Scan(&a, &b)

	fmt.Println(add(a, b))
	fmt.Println(addAndSub(a, b))
}

func getSum(nums ...int) int {
	sum := 0
	for i := 0; i < len(nums); i++ {
		sum += nums[i]
	}

	return sum
}

func main21() {
	fmt.Println(getSum(1, 2, 3, 55, 66))
}

func update(arr *[5]int) {
	arr[0] = 100
}

func main22() {
	arr := [5]int{1, 2, 3, 4, 5}
	update(&arr)
	fmt.Println(arr)
}

func update2(s []int) {
	s[0] = 100
}

func main23() {
	s := []int{1, 2, 3, 4}
	update2(s)
	fmt.Println(s)
}

func main24() {
	var stringBuilder bytes.Buffer
	stringBuilder.WriteString("part1")
	stringBuilder.WriteString("part2")
	fmt.Println(stringBuilder.String())
}

func main25() {
	//s1 := "hello"
	s2 := "你好"

	fmt.Printf("%s", string([]rune(s2)[1]))
}

func main26() {
	s := "In my opinion, Java is the best language of the world"
	strArr := strings.Split(s, "Java")
	var strBuilder bytes.Buffer

	strBuilder.WriteString(strArr[0])
	strBuilder.WriteString("Go")
	strBuilder.WriteString(strArr[1])

	fmt.Println(strBuilder.String())

	s2 := "In my opinion, Java is the best language of the world"
	fmt.Println(strings.Replace(s2, "Java", "Go", 1))
}

func main27() {
	a := 1
	ptr := &a

	fmt.Println(ptr)
	fmt.Println(*ptr)
}

func modifyNumByVal(num int) {
	num += 10
}

func modifyNumByPointer(num *int) {
	*num += 10
}

func main28() {
	num := 10
	modifyNumByVal(num)
	fmt.Println("值传递, num: ", num)

	modifyNumByPointer(&num)
	fmt.Println("引用传递, num: ", num)
}

func main29() {
	str := new(string)

	*str = "hello"
	fmt.Println(*str)
}

func main30() {
	// 定义命令行
	mode := flag.String("mod", "", "运行模式, 可以设置为 fast")
	// 解析命令行
	flag.Parse()
	fmt.Println("运行模式为: ", *mode)
}

func main31() {
	str := "1"
	strToInt, _ := strconv.ParseInt(str, 2, 64)
	fmt.Printf("%T\n", strToInt)

	intVal := 10
	intToStr := fmt.Sprint(intVal)
	fmt.Printf("%T\n", intToStr)
}

func main32() {
	arr := [5]int{1, 2, 3, 4, 5}

	for _, v := range arr {
		fmt.Println(v)
	}
}

func main33() {
	a := [5]int{1, 2, 3, 4, 5}
	fmt.Println(a, a[1:3])
	fmt.Println(a, a[:3])
	fmt.Println(a, a[3:])
	fmt.Println(a, a[:])
	fmt.Println(a, a[0:0])
}

func main34() {
	var list []int
	fmt.Println(list)

	list = append(list, 1, 2, 3)
	fmt.Println(list)
}

func main35() {
	a := make([]string, 2)
	b := make([]string, 2, 10)

	fmt.Println(len(a), len(b))

	a = append(a, "hello")
	fmt.Println(len(a), len(b))
}

func main36() {
	nums := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	slice := nums[4:6]

	fmt.Println("len:", len(slice))
	fmt.Println("values:", slice)
	fmt.Println("cap:", cap(slice))

	slice = slice[:cap(slice)]
	fmt.Println("index 4:", slice[3])
}

func main37() {
	slice1 := []int{1, 2, 3, 4, 5}
	slice2 := []int{6, 7, 8}

	//copy(slice2, slice1)
	//fmt.Println(slice2)
	copy(slice1, slice2)
	fmt.Println(slice1)
}

func main38() {
	slice1 := []int{1, 2, 3, 4, 5, 6}
	slice2 := slice1
	slice3 := make([]int, 10, 100)
	copy(slice3, slice1)

	slice2[4] = math.MaxInt64

	fmt.Println(slice1)
	fmt.Println(slice2)
	fmt.Println(slice3)
}

func main39() {
	m := make(map[string]string)
	m["apple"] = "苹果"
	m["cat"] = "猫"
	m["dog"] = "狗"
	m["banana"] = "香蕉"
	m["fox"] = "狐狸"

	for k, v := range m {
		fmt.Println(k, v)
	}
	fmt.Println()
	fmt.Println("start delete ... ")
	fmt.Println()

	delete(m, "dog")
	delete(m, "cat")
	delete(m, "apple")

	for k, v := range m {
		fmt.Println(k, v)
	}

	num := new(int)
	*num = 10
	fmt.Println(num, *num)
}

func main40() {
	// 不同变量为 nil 时的地址是相同的
	var list []int
	var p *int

	fmt.Printf("%p\n", list)
	fmt.Printf("%p\n", p)
}

func main41() {
	m := new(map[string]string)
	(*m)["apple"] = "苹果"
	fmt.Println((*m)["apple"])
}

func getVal() int {
	return 100
}

func fn1(fn func() int) int {
	return fn()
}

func main42() {
	fmt.Println(fn1(getVal))
}

func fn2() (name string, age int) {
	name = "zhangsan"
	age = 18
	return
}

func main43() {
	fmt.Println(fn2())
}

func main44() {
	maxVal := func(a, b int) int {
		if a > b {
			return a
		} else {
			return b
		}
	}(10, 20)
	fmt.Println(maxVal)
}

// 1.Mdwas(fn func(event EventCreate){
// })
// {
// fn()
// }
func sequenceGenerator() func() int {
	a := 1

	return func() int {
		a += 1
		return a
	}
}
func MiddleHandler() {

}
func main45() {
	// 闭包
	next := sequenceGenerator()

	fmt.Println(next())
	fmt.Println(next())
	fmt.Println(next())

	anotherNext := sequenceGenerator()
	fmt.Println(anotherNext())
	fmt.Println(anotherNext())
}

type Student struct {
	name string
	age  int
}

func main46() {
	var stu1 Student
	stu1.name = "zhangsan"
	stu1.age = 18

	fmt.Println(stu1)

	stu2 := Student{
		"lisi",
		18,
	}

	fmt.Println(stu2)
}

func main47() {
	var stringBuilder bytes.Buffer

	stringBuilder.WriteString("123")
}

func main48() {
	var arr = [10]int{1, 2, 3, 4, 5}
	arr[8] = 9
	fmt.Printf("%T", arr)
}

func main49() {
	arr := [6][6]int{
		{1, 2, 3, 4, 5, 6},
	}

	fmt.Println(arr)
}

func main50() {
	arr := []int{1, 2, 3, 4, 5, 6}

	a := arr
	b := arr

	fmt.Printf("%p, %p, %p", arr, a, b)
}

func main51() {
	arr := []int{1, 2, 3, 4, 5, 6}

	for i := range arr {
		arr[i] = 100
	}

	fmt.Println(arr)
}

func main52() {
	m := make(map[string]string)
	m["k1"] = "v1"
	m["k2"] = "v2"
	m["k3"] = "v3"

	for k, v := range m {
		fmt.Println("k: ", k, "v: ", v)
	}
}

func main53() {
	nums := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	slice := nums[4:6]

	fmt.Println("len:", len(slice))
	fmt.Println("values:", slice)
	fmt.Println("cap:", cap(slice))
	fmt.Printf("%p\n", &nums[4])
	fmt.Printf("%p", &slice[0])

	//slice = slice[:cap(slice)]
	//fmt.Println("index 4:", slice[3])
}

func main54() {
	l := list.New()
	l.PushBack(1)
	l.PushBack("aaa")

	for i := l.Front(); i != nil; i = i.Next() {
		fmt.Println(i.Value)
	}
}

type IWorker interface {
	work(a, b int)
	sleep(time time.Time)
}

type stu struct {
	name string
}

func (s stu) work(a, b int) {
	fmt.Println(a * b)
}

func (stu) sleep(time time.Time) {

}

type stu1 struct {
	name string
}

func (stu1) work(a, b int) {
	fmt.Println(a + b)
}

func (stu1) sleep(time time.Time) {

}

func GoWork(iw IWorker) {
	iw.work(1, 2)
	iw.sleep(time.Now())
}

func main55() {
	s := stu{}
	s1 := stu1{}
	GoWork(s)
	GoWork(s1)
}

type Animal interface {
	Speak()
}

type Dog struct {
	name string
}

type Cat struct {
	name string
}

func (d Dog) Speak() {
	fmt.Println("Dog speak")
}

func (c Cat) Speak() {
	fmt.Println("Cat speak")
}

func AnimalSpeak(animal Animal) {
	animal.Speak()
}

func main56() {
	dog := Dog{name: "cat"}
	cat := Cat{name: "Dog"}

	AnimalSpeak(dog)
	AnimalSpeak(cat)
}

func fn() func() {
	a := 1
	return func() {
		a += 1
		fmt.Println(a)
	}
}

func main57() {
	fnn := fn()
	fnn()
	fnn()
	fnn()
	fnn()
	fnn()
}

func addd(ints ...int) int {
	sum := 0

	for _, v := range ints {
		sum += v
	}

	return sum
}

func (Cat) eat() {
	fmt.Println("eat")
}

func main58() {
	cat := Cat{}
	cat.eat()
}

func main59() {
	conn, err := net.Dial("udp", "stun.l.google.com:19302")
	if err != nil {
		panic(err)
	}
	client, _ := stun.NewClient(conn)
	message := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
	if err := client.Do(message, func(res stun.Event) {
		if res.Error != nil {
			fmt.Println("Error:", res.Error)
			return
		}
		var xorAddr stun.XORMappedAddress
		if err := xorAddr.GetFrom(res.Message); err != nil {
			fmt.Println("Failed to get address:", err)
			return
		}
		fmt.Printf("Your external IP: %s:%d\n", xorAddr.IP, xorAddr.Port)
	}); err != nil {
		panic(err)
	}
}

func main60() {
	// 连接到 coturn 服务器，地址为 cpolar 暴露的公网地址和端口
	conn, err := net.Dial("tcp", "1.tcp.vip.cpolar.top:11285")
	if err != nil {
		log.Fatalf("无法连接到服务器: %v\n", err)
	}
	defer conn.Close()

	// 创建 STUN 客户端
	client, _ := stun.NewClient(conn)

	// 设置认证信息（用户名和密码）
	username := "avenir" // 替换为你在 coturn 设置的用户名
	password := "test"   // 替换为你在 coturn 设置的密码

	// 创建一个 STUN 绑定请求消息，包含用户名和 MessageIntegrity
	message := stun.MustBuild(
		stun.TransactionID,
		stun.BindingRequest,
		stun.NewUsername(username),           // 设置用户名
		stun.NewShortTermIntegrity(password), // 使用 MessageIntegrity 验证
	)

	// 发送 STUN 请求，并等待响应
	if err := client.Do(message, func(res stun.Event) {
		if res.Error != nil {
			log.Fatalf("STUN 请求错误: %v\n", res.Error)
		}
		// 解析返回的外部 IP 和端口
		var xorAddr stun.XORMappedAddress
		if err := xorAddr.GetFrom(res.Message); err != nil {
			log.Fatalf("无法获取外部地址: %v\n", err)
		}
		// 打印外部 IP 和端口
		fmt.Printf("外部 IP: %s，端口: %d\n", xorAddr.IP, xorAddr.Port)
	}); err != nil {
		log.Fatalf("发送请求失败: %v\n", err)
	}

	// 关闭 STUN 客户端
	client.Close()
}

// TCPAdapter 封装一个 net.Conn 以符合 net.PacketConn 接口
type TCPAdapter struct {
	conn net.Conn
}

func (t *TCPAdapter) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
	n, err = t.conn.Read(p)
	addr = t.conn.RemoteAddr()
	return
}

func (t *TCPAdapter) WriteTo(p []byte, addr net.Addr) (n int, err error) {
	return t.conn.Write(p)
}

func (t *TCPAdapter) Close() error {
	return t.conn.Close()
}

func (t *TCPAdapter) LocalAddr() net.Addr {
	return t.conn.LocalAddr()
}

func (t *TCPAdapter) SetDeadline(deadline time.Time) error {
	return t.conn.SetDeadline(deadline)
}

func (t *TCPAdapter) SetReadDeadline(deadline time.Time) error {
	return t.conn.SetReadDeadline(deadline)
}

func (t *TCPAdapter) SetWriteDeadline(deadline time.Time) error {
	return t.conn.SetWriteDeadline(deadline)
}

func main61() {
	// 连接到 TURN 服务器
	conn, err := net.Dial("tcp", "1.tcp.vip.cpolar.top:11285")
	if err != nil {
		log.Fatalf("无法连接到服务器: %v", err)
	}

	adapter := &TCPAdapter{conn: conn}

	client, err := turn.NewClient(&turn.ClientConfig{
		Conn:     adapter,
		Username: "avenir",
		Password: "test",
		Realm:    "test.com",
	})
	if err != nil {
		log.Fatalf("创建 TURN 客户端失败: %v", err)
	}
	defer client.Close()

	if err := client.Listen(); err != nil {
		log.Fatalf("监听失败: %v", err)
	}

	relayConn, err := client.Allocate()
	if err != nil {
		log.Fatalf("分配地址失败: %v", err)
	}
	defer relayConn.Close()

	fmt.Printf("分配的 Relay 地址: %s\n", relayConn.LocalAddr().String())

	buffer := make([]byte, 1500)
	for {
		n, addr, err := relayConn.ReadFrom(buffer)
		if err != nil {
			log.Printf("读取消息失败: %v", err)
			continue
		}
		fmt.Printf("从 %s 收到消息: %s\n", addr.String(), string(buffer[:n]))
	}
}
